package com.app.service;

import com.app.alarm.R;
import com.app.model.AlarmDataManager;
import com.app.model.AlarmDataManager.AlarmLoader;
import com.app.util.ApplicationMediator;
import com.app.util.VolumeManager;
import com.app.view_controller.AlarmReceiverFragment;
import com.app.view_controller.AlarmRecevierActivity;
import com.app.view_controller.ContentActivity;
import com.app.view_controller.ListFragment;

import android.R.anim;
import android.animation.Animator.AnimatorListener;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

public class AlarmService extends Service {

	public static final String STOP_ALARM_SERVICE = "stop alarm";
	public static final String SERVICE_RUNNING = "service running";
	public static final String START_ALARM_SERVICE = "set alarm";
	public static final String POSTPONE_ALARM = "postpone";
	public static final String START_ACTIVITY_FROM_NOTIFICATION = "start activity from notification";
	public static final String ACTION_CLOSE_ACTIVITY = "com.app.view_controller.AlarmreceiverActivity.ACTION_CLOSE";
	public static final String MISCELLANEOUS_SHARED_PREFERENCES = "miscellaneous shared preferences";

	private static final String TAG = "ALARM_SERVICE";
	private static final boolean DEBUG = true;
	private static final int ALARM_RUNNING_NOTIFICATION = 1;
	private static boolean isCreated = false;
	private VolumeManager audio;
	private Ringtone tone;
	private int startVolumeLevel;
	private int defaultVolume;
	private AlarmDataManager mAlarm;
	private LocalBinder IBinder;
	private AlarmService thisService;
	public static final String SEND_ALARM_TO_SERVICE = "send alarm to service";
	public static final String START_ALARM_RINGTONE = "start alarm";
	private static AlarmDataManager staticAlarm;

	public AlarmService() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * Class for clients to access. Because we know this service always runs in
	 * the same process as its clients, we don't need to deal with IPC.
	 */
	public class LocalBinder extends Binder {
		public AlarmService getService() {
			return AlarmService.this;
		}
	}

	private static void setServiceCreated(boolean value) {
		isCreated = value;
	}

	private static void setCurrentAlarm(AlarmDataManager alarm) {
		staticAlarm = alarm;
	}

	public static AlarmDataManager getCurrentAlarm() {
		return staticAlarm;
	}

	public static boolean isServiceCreated() {
		return isCreated;
	}

	@Override
	public void onCreate() {
		Toast.makeText(this, "service created", 1000).show();
		IBinder = new LocalBinder();
		setServiceCreated(true);
		thisService = this;
		super.onCreate();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		if (intent == null)
			return super.onStartCommand(intent, flags, startId);
		String action = intent.getAction();
		if (DEBUG)
			Log.d(TAG, "getaction  " + action);

		if (START_ALARM_SERVICE.equals(action)) {
			startAlarm(intent);
		}

		if (AlarmService.START_ALARM_RINGTONE.equals(action) && mAlarm != null) {
			startRingtone();
		}

		if (START_ACTIVITY_FROM_NOTIFICATION.equals(action)) {
			startActivityFromNotification(intent);
		}

		if (POSTPONE_ALARM.equals(action) && mAlarm != null) {
			postponeAlarm(intent);
		}

		if (STOP_ALARM_SERVICE.equals(action) && mAlarm != null) {
			stopAlarmService(intent);
		}
		return super.onStartCommand(intent, flags, startId);
	}

	private void startAlarm(Intent intent) {
		mAlarm = AlarmLoader.getFromStorage(intent.getStringExtra(ContentActivity.ALARM_MESSAGE), this);
		setCurrentAlarm(mAlarm);
		audio = VolumeManager.getVolumeManagerInstance(this);
		defaultVolume = audio.getStreamVolume(VolumeManager.STREAM_ALARM);
		NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
		mNotificationManager.cancel(HandleAlarmNotificationService.ALARM_SET_NOTIFICATION_ID);
		createNotification();
		//Start activity
		Intent startIntent = new Intent(this, AlarmRecevierActivity.class);
		startIntent.setAction("start from notification");
		if (getSharedPreferences(MISCELLANEOUS_SHARED_PREFERENCES, MODE_PRIVATE).getBoolean(ContentActivity.IS_CONTENTACTIVITY_FOREGROUND, false))
			startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		else
			startIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
		startActivity(startIntent);
		//Start ringtone
		startRingtone();
	}

	private void startRingtone() {
		if (DEBUG)
			Log.d(TAG, "entrato start alarm");
		// If the application should control the alarm volume set the new audio stream volume.
		if (mAlarm.isControlledAlarmVolume())
			audio.setStreamVolume(RingtoneManager.TYPE_ALARM, mAlarm.getAlarmVolumeLevel(), 0);
		// Get the value of the volume. It may be the default one or the imposed one.
		final int currentVolume = audio.getStreamVolume(RingtoneManager.TYPE_ALARM);
		// Retrieve the chosen ringtone.
		if (tone == null)
			tone = RingtoneManager.getRingtone(this, mAlarm.getAlarmToneUri());
		tone.setStreamType(RingtoneManager.TYPE_ALARM);
		// If the volume level is incremental the starting value is 0 otherwise it's the current volume level.
		if (mAlarm.isIncrementalVolume())
			startVolumeLevel = 0;
		else
			startVolumeLevel = currentVolume;
		final Handler handler = new Handler();
		handler.post(new Runnable() {

			@Override
			public void run() {
				// Set the stram volume level
				audio.setStreamVolume(RingtoneManager.TYPE_ALARM, startVolumeLevel, 0);
				// Start the ringtone
				if (tone != null && !tone.isPlaying())
					tone.play();
				// Increase the volume level
				startVolumeLevel++;
				// Loop the method run until the startVolumeLevel gets higher that the imposed volume.
				if (startVolumeLevel <= currentVolume)
					handler.postDelayed(this, 2000);
			}
		});
	}

	private void startActivityFromNotification(Intent intent) {
		SharedPreferences preferences = getSharedPreferences(MISCELLANEOUS_SHARED_PREFERENCES, MODE_PRIVATE);
		if (!preferences.getBoolean(AlarmRecevierActivity.IS_RECEIVERACTIVITY_FOREGROUND, false)) {
			Intent startIntent = new Intent(this, AlarmRecevierActivity.class);
			startIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
			if (!getSharedPreferences(MISCELLANEOUS_SHARED_PREFERENCES, MODE_PRIVATE).getBoolean(
					AlarmRecevierActivity.IS_RECEIVERACTIVITY_FOREGROUND, false))
				startActivity(startIntent);
		}
	}

	private void postponeAlarm(Intent intent) {
		tone.stop();
		Runnable r = new Runnable() {

			@Override
			public void run() {
				if (tone != null)
					tone.play();
				Intent notIntent = new Intent(thisService, AlarmRecevierActivity.class);
				notIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				startActivity(notIntent);
			}
		};
		if (DEBUG)
			Log.d(TAG, "getpostponetimeinmillis " + mAlarm.getPostponeTimeInMillis());
		new Handler().postDelayed(r, mAlarm.getPostponeTimeInMillis());
	}

	private void stopAlarmService(Intent intent) {
		Intent stopActivityIntent = new Intent(ACTION_CLOSE_ACTIVITY);
		sendBroadcast(stopActivityIntent);
		stopSelf();
	}

	private void adjustRingtoneAndNotificationVolumeLevel() {
		audio.restoreDefaultVolumeLevel(VolumeManager.STREAM_RING);
		audio.restoreDefaultVolumeLevel(VolumeManager.STREAM_NOTIFICATION);

	}

	private void createNotification() {
		Intent startActivityIntent = new Intent(this, AlarmService.class);
		startActivityIntent.setAction(START_ACTIVITY_FROM_NOTIFICATION);
		PendingIntent startActivityPendingIntent = PendingIntent.getService(this, 0, startActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT);

		Intent stopIntent = new Intent(this, AlarmService.class);
		stopIntent.setAction(STOP_ALARM_SERVICE);
		PendingIntent stopPendingIntent = PendingIntent.getService(this, 0, stopIntent, PendingIntent.FLAG_UPDATE_CURRENT);

		Intent postponeIntent = new Intent(this, AlarmService.class);
		postponeIntent.setAction(POSTPONE_ALARM);
		PendingIntent postponePendingIntent = PendingIntent.getService(this, 0, postponeIntent, PendingIntent.FLAG_UPDATE_CURRENT);

		NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
		mBuilder.setSmallIcon(R.drawable.alarm_icon)
				.setContentTitle(this.getResources().getString(R.string.app_name))
				.setPriority(NotificationCompat.PRIORITY_MAX)
				.addAction(android.R.drawable.ic_media_pause, getResources().getString(R.string.Postpone), postponePendingIntent)
				.addAction(android.R.drawable.ic_menu_close_clear_cancel, getResources().getString(R.string.Cancel),
						stopPendingIntent);

		mBuilder.setContentIntent(startActivityPendingIntent);

		NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
		// mId allows you to update the notification later on.
		Notification notification = mBuilder.build();
		//	notification.flags |= Notification.FLAG_ONGOING_EVENT;
		mNotificationManager.notify(ALARM_RUNNING_NOTIFICATION, notification);
	}

	@Override
	public void onDestroy() {
		if (DEBUG)
			Log.d(TAG, "ondestroyservice called  -  default alarm volume " + defaultVolume);
		audio.setStreamVolume(RingtoneManager.TYPE_ALARM, defaultVolume, 5);
		tone.stop();
		tone = null;
		adjustRingtoneAndNotificationVolumeLevel();
		setCurrentAlarm(null);
		mAlarm.removeAlarm();
		mAlarm.savetoStorage();
		Intent updateListIntent = new Intent(ListFragment.ACTION_UPDATE_LIST);
		sendBroadcast(updateListIntent);
		NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
		mNotificationManager.cancel(ALARM_RUNNING_NOTIFICATION);
		setServiceCreated(false);
		super.onDestroy();
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return IBinder;
	}
}
